package com.ocom.xcxapi.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ocom.common.constant.WxServiceUrl;
import com.ocom.common.entity.card.*;
import com.ocom.common.entity.payconfig.EntityDishesClass;
import com.ocom.common.entity.payconfig.EntityDishesInfo;
import com.ocom.common.enums.ConsStateEnum;
import com.ocom.common.enums.ResultEnum;
import com.ocom.common.request.payconfig.GetDishesInfoDetailListRequest;
import com.ocom.common.request.payconfig.GetTollPointInfoRequest;
import com.ocom.common.request.payconfig.MealPlanInfoRequest;
import com.ocom.common.request.payconfig.mealorder.GetOrderPlanDishesRequest;
import com.ocom.common.request.payconfig.mealorder.GetOrderPlanDishesResponse;
import com.ocom.common.request.payhandle.DishesInfoVo;
import com.ocom.common.request.payhandle.GetRecentOrderRecordsRequest;
import com.ocom.common.request.payhandle.OrderDishesPayRequest;
import com.ocom.common.request.ugcapi.OrderedShowRequest;
import com.ocom.common.request.ugcapi.order.*;
import com.ocom.common.request.web.ConsTimeConfigOnShowRequest;
import com.ocom.common.resp.Result;
import com.ocom.common.utils.*;
import com.ocom.common.vo.payconfig.kitchenprinter.PlanKitchenPrinterRequest;
import com.ocom.redis.util.RedisUtil;
import com.ocom.security.authentication.YoCiUser;
import com.ocom.security.utils.SecurityUtils;
import com.ocom.xcxapi.client.HumanClientService;
import com.ocom.xcxapi.client.PayConfigClientService;
import com.ocom.xcxapi.client.PayHandleClientService;
import com.ocom.xcxapi.client.XfRecordFeign;
import com.ocom.xcxapi.vo.OrderedShowDishesListVo;
import com.ocom.xcxapi.vo.OrderedShowVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@PreAuthorize("hasRole('ROLE_XCX')")
@RestController
public class OrderController {


    @Resource
    private RedisUtil redisUtil;


    @Autowired
    private PayConfigClientService payConfigClientService;
    @Autowired
    private PayHandleClientService payHandleClientService;
    @Autowired
    private XfRecordFeign xfRecordFeign;
    @Autowired
    private HumanClientService humanClientService;

    /**
     * 5.1餐厅列表（order/loadRestaurants）
     */
    @PostMapping(WxServiceUrl.Url_OrderLoadRestaurants)
    public Result LoadRestaurants(@RequestBody LoadRestaurantsRequest request) {
        YoCiUser ciUser = SecurityUtils.getYoCiUser();
        request.setComId(ciUser.getComId());
        String strPoints = "";
        if (null != request.getPointId()) {
            strPoints = String.valueOf(request.getPointId());
        }
        request.setStrPoints(strPoints);
        request.setPage(1);
        request.setSize(500);
        Result result = payConfigClientService.restaurantList(request);
        if (200 == result.getCode()) {
            try {
                List<EntityPointConfig> entityPointConfigs = JSON.parseArray(JSON.toJSONString(result.getData()), EntityPointConfig.class);
                ConsTimeConfigOnShowRequest consTimeConfigOnShowRequest = new ConsTimeConfigOnShowRequest();
                consTimeConfigOnShowRequest.setSize(5000);
                consTimeConfigOnShowRequest.setPage(1);
                consTimeConfigOnShowRequest.setComId(ciUser.getComId());
                Result mealTimeResult = this.getMealTime(consTimeConfigOnShowRequest);
                if (200 == mealTimeResult.getCode()) {
                    JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(mealTimeResult.getData()));
                    Map<Integer, List<EntityXfMealTime>> listMap = JSON.parseArray(jsonObject.getString("list"), EntityXfMealTime.class).stream().collect(Collectors.groupingBy(e -> e.getPointId()));

                    for (EntityPointConfig entityPointConfig : entityPointConfigs) {
                        entityPointConfig.setMealTimes(listMap.getOrDefault(entityPointConfig.getPointId(), listMap.get(0)));
                    }
                }
                result = ResultUtil.success(entityPointConfigs);
            }catch (Exception e) {
                e.printStackTrace();
            }

        }
        return result;
    }

    /**
     * 5.2点餐菜品列表（order/onShow）
     */
    @PostMapping(WxServiceUrl.Url_OrderOnShow)
    public Result onShow(@RequestBody OrderShowRequest request) {
        YoCiUser ciUser = SecurityUtils.getYoCiUser();
        request.setComId(ciUser.getComId());


        Integer mealNo = 0;

//        try {
//            ConsTimeConfigOnShowRequest  request1 =new ConsTimeConfigOnShowRequest();
//            request1.setComId(ciUser.getComId());
//            request1.setPage(1);
//            request1.setSize(100);
//            Result result2 = payConfigClientService.GetMealTimeInfo(request1);
//            JSONObject jsonObject2 = JSON.parseObject(JSON.toJSONString(result2.getData()));
//            List<GetMealTimeDto> mealTimeList = JSON.parseArray(JSON.toJSONString(jsonObject2.get("list")),GetMealTimeDto.class);
//            if (mealTimeList != null) {
//                for (GetMealTimeDto entityXfMealTime : mealTimeList) {
//                    if (DateUtils.isInTimeFor2(new Date(), entityXfMealTime.getBeginTime(), entityXfMealTime.getEndTime())) {
//                        mealNo = Integer.valueOf(entityXfMealTime.getMealNo());
//                        break;
//                    }
//                }
//            }
//        }catch (Exception e){
//            log.error("菜品列表计算餐段异常 【{}】",e);
//        }
//
//        log.error("菜品列表计算当前餐段 【{}】",mealNo);


        GetOrderPlanDishesRequest orderPlanDishesRequest = new GetOrderPlanDishesRequest();
        orderPlanDishesRequest.setComId(request.getComId());
        orderPlanDishesRequest.setMealDate(DateUtil.getDate());
        orderPlanDishesRequest.setMealNo(0);
        orderPlanDishesRequest.setMerchId(0);
        orderPlanDishesRequest.setPointId(request.getPointId());
        orderPlanDishesRequest.setReceiptId(request.getReceiptId());
        Result result = payConfigClientService.getOrderPlanDishes(orderPlanDishesRequest);
        if (200 != result.getCode()) {
            return ResultUtil.error(ResultEnum.Err_1001);
        }

        List<GetOrderPlanDishesResponse> dishList =  JSON.parseArray(JSON.toJSONString(result.getData()), GetOrderPlanDishesResponse.class);

        GetRecentOrderRecordsRequest recentOrderRecordsRequest = new GetRecentOrderRecordsRequest();
        recentOrderRecordsRequest.setCompanyId(request.getComId());
        recentOrderRecordsRequest.setOpenId(ciUser.getUsername());
        recentOrderRecordsRequest.setPId(0);
        recentOrderRecordsRequest.setPointId(-1);
        recentOrderRecordsRequest.setBeginDate(DateUtil.getDate());
        recentOrderRecordsRequest.setPage(1);
        recentOrderRecordsRequest.setSize(1);
        result = payHandleClientService.getRecentOrderRecords(recentOrderRecordsRequest);
        if (200 != result.getCode()) {
            return result;
        }
        List<EntityXfRecordProcess> recordProcessList = JSON.parseArray(JSON.toJSONString(result.getData()), EntityXfRecordProcess.class);
        List<EntityXfGoodListOrg> xfGoodListOrgs = new ArrayList<>();

        if (0 < recordProcessList.size() ) {
            EntityXfRecordProcess recordProcess = recordProcessList.get(0);
            if ((null != recordProcess.getPointId() && null != recordProcess.getPayState()) &&request.getPointId().intValue() == recordProcess.getPointId() && 0 == recordProcess.getPayState()) {
                OrderedShowRequest orderedShowRequest = new OrderedShowRequest();
                orderedShowRequest.setOrderNo(recordProcess.getOrderNo());
                orderedShowRequest.setComId(recordProcess.getComId());
                orderedShowRequest.setMonthValue(recordProcess.getMonthValue());
                result = xfRecordFeign.getOrderDishesDetail(orderedShowRequest);
                if (200 == result.getCode() && null != result.getData()) {
                    xfGoodListOrgs = JSON.parseArray(JSON.toJSONString(result.getData()), EntityXfGoodListOrg.class);
                }
            }
        }
        result = payConfigClientService.dishesClassOfCom(request.getComId());
        if (200 != result.getCode() || null == result.getData()) {
            return result;
        }

        List<EntityDishesClass> dishesClassList = JSON.parseArray(JSON.toJSONString(result.getData()), EntityDishesClass.class);

        Set<EntityDishesClass> classList = new HashSet<>();
        for (EntityDishesClass entityDishesClass : dishesClassList) {
            for (GetOrderPlanDishesResponse planDishesResponse :dishList){
                if (entityDishesClass.getDishesClassId().equals(planDishesResponse.getDishesClassId())) {
                    classList.add(entityDishesClass);
                }
            }
        }

        Map<String, Object> map = new HashMap<>();
        map.put("dishList",dishList);
        map.put("orderedList",xfGoodListOrgs);
        map.put("classList",classList);

        return ResultUtil.success(map);
    }

    /**
     * 5.3点餐记录（order/recentRecords）
     */
    @PostMapping(WxServiceUrl.Url_OrderRecentRecords)
    public Result recentRecords(@RequestBody RecentRecordsRequest request) {
        YoCiUser ciUser = SecurityUtils.getYoCiUser();
        request.setComId(ciUser.getComId());
        request.setOpenId(ciUser.getUsername());

        GetRecentOrderRecordsRequest recentOrderRecordsRequest = new GetRecentOrderRecordsRequest();
        recentOrderRecordsRequest.setCompanyId(request.getComId());
        recentOrderRecordsRequest.setOpenId(request.getOpenId());
        recentOrderRecordsRequest.setPId(0);
        recentOrderRecordsRequest.setPointId(-1);
        recentOrderRecordsRequest.setBeginDate(DateUtil.getDate());
        recentOrderRecordsRequest.setPage(request.getPage());
        recentOrderRecordsRequest.setSize(request.getSize());

        return payHandleClientService.getRecentOrderRecords(recentOrderRecordsRequest);
    }

    /**
     * 5.4最近配送地址（order/recentAddress）
     */
    @PostMapping(WxServiceUrl.Url_OrderRecentAddress)
    public Result recentAddress(@RequestBody RecentAddressRequest request) {
        YoCiUser ciUser = SecurityUtils.getYoCiUser();
        request.setComId(ciUser.getComId());
        request.setOpenId(ciUser.getUsername());

        Map<String, Object> map = new HashMap<>();
        Result result = payHandleClientService.getRecentAddress(request);
        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(result.getData()));
        map.put("list", jsonObject.get("list"));
        return ResultUtil.success(map);
    }

    /**
     * 5.5获取支付通道
     */
    @PostMapping(WxServiceUrl.Url_OrderPayWay)
    public Result payWay(@RequestBody PayWayRequest request) {
        YoCiUser ciUser = SecurityUtils.getYoCiUser();
        request.setComId(ciUser.getComId());

        GetTollPointInfoRequest tollPointInfoRequest = new GetTollPointInfoRequest();
        tollPointInfoRequest.setCom_id(request.getComId());
        tollPointInfoRequest.setPoint_id(request.getPointId());
        tollPointInfoRequest.setSize(1);
        Result result = payConfigClientService.getTollPointInfo(tollPointInfoRequest);
        if (200 != result.getCode() || null == result.getData()) {
            return ResultUtil.error(ResultEnum.Err_1001);

        }
        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(result.getData()));
        List<EntityXfPointInfo> pointInfos = JSON.parseArray(jsonObject.get("list").toString(),EntityXfPointInfo.class);
        if (null == pointInfos || 0 == pointInfos.size()) {
            return ResultUtil.error(ResultEnum.Err_1001);

        }
        EntityXfPointInfo entityXfPointInfo = pointInfos.get(0);


        return payConfigClientService.getRechargePayWay(request.getComId(), Long.valueOf(entityXfPointInfo.getMerchId()));
    }

    /**
     * 5.6提交点餐（order/orderSubmit）
     */
    @PostMapping(WxServiceUrl.Url_OrderOrderSubmit)
    public Result orderSubmit(@RequestBody OrderSubmitRequest request) {
        YoCiUser ciUser = SecurityUtils.getYoCiUser();
        request.setComId(ciUser.getComId());
        request.setOpenId(ciUser.getUsername());

        boolean lock2 = redisUtil.lock("xcxOrder:comId:" + ciUser.getComId()+"#pId:"+request.getPId(), 5);
        if (!lock2) {
            return ResultUtil.error(ResultEnum.Err_4102);
        }

        log.info("微信小程序点餐请求 【{}】",request);

        int dishesPrice = request.getMealMenuInfo().stream().mapToInt(DishesInfoVo:: getDishesPrice).sum();
        if (dishesPrice != request.getMealPrice()) {
            return ResultUtil.error(ResultEnum.Err_4134);
        }

//        Result result = humanClientService.GetWxPerson(null, request.getOpenId());
//        if (200 != result.getCode() || null == result.getData()) {
//            return ResultUtil.error(ResultEnum.Err_303);
//        }
//
//        EntityWechatPerInfo wechatPerInfo = JSON.parseObject(JSON.toJSONString(result.getData()), EntityWechatPerInfo.class);

        String tradeNo = DateUtil.getStrDate(new Date(), "yyyyMMddHHmmss") + RandomUtil.generateNumber(4);
        tradeNo = "DA" + NumConvertUtil.IntToHexStringNum(request.getComId().intValue(),6) + tradeNo ;

        OrderDishesPayRequest orderDishesPayRequest = new OrderDishesPayRequest();
        orderDishesPayRequest.setComId(request.getComId());
        orderDishesPayRequest.setMachNo("00000000");
        orderDishesPayRequest.setTradeNo(tradeNo);
        orderDishesPayRequest.setAmount(request.getMealPrice());
        orderDishesPayRequest.setType(request.getType());
        orderDishesPayRequest.setConsType(1);
        orderDishesPayRequest.setOpenId(request.getOpenId());
        orderDishesPayRequest.setPId(request.getPId());
        orderDishesPayRequest.setConsState(ConsStateEnum.MEAL.getKey());
        orderDishesPayRequest.setPayWay(request.getPayWay());
        orderDishesPayRequest.setPointId(request.getPointId());
        orderDishesPayRequest.setReceiptId(request.getReceiptId());
        orderDishesPayRequest.setReceiptName(request.getAddress());
        orderDishesPayRequest.setRemark(request.getRemark());
        if (request.getTableId() != null) {
            orderDishesPayRequest.setReceiptId(request.getTableId());
        }
//        orderDishesPayRequest.setReceiptName();
//        orderDishesPayRequest.setMealDate();
//        orderDishesPayRequest.setMealNo();

        orderDishesPayRequest.setDishesInfo(request.getMealMenuInfo());
        Result rt =  payHandleClientService.orderDishesPay2(orderDishesPayRequest);
        log.info("微信点餐返回 【{}】",rt);

        if(rt.getCode()==200 && orderDishesPayRequest.getType()==7){
            try {
                log.info("开始打印订单 订单：【{}】，回调：【{}】",orderDishesPayRequest,rt);
                PlanKitchenPrinterRequest planKitchenPrinterRequest = new PlanKitchenPrinterRequest();
                planKitchenPrinterRequest.setComId(orderDishesPayRequest.getComId());
                planKitchenPrinterRequest.setPointId(orderDishesPayRequest.getPointId().longValue());
                planKitchenPrinterRequest.setOrderNo(orderDishesPayRequest.getTradeNo());
                planKitchenPrinterRequest.setCheckPrint(true);

                log.info("开始打印订单 planKitchenPrinter：【{}】",planKitchenPrinterRequest);
                Result printResult = payConfigClientService.planKitchenPrinter(planKitchenPrinterRequest);
                log.info("订单打印结果【{}】",printResult);

            }catch (Exception e) {
                e.printStackTrace();
                log.info("订单打印异常 【{}】【{}】",orderDishesPayRequest,rt);
            }
        }
        return  rt;
    }

    /**
     * 6.5已点餐查询（OrderPage/orderedShow）
     */
    @PostMapping(WxServiceUrl.Url_OrderOrderedShow)
    public Result orderedShow(@RequestBody Map<String, Object> map) {
        OrderedShowRequest request = JSON.parseObject(JSON.toJSONString(map), OrderedShowRequest.class);

        log.info("点餐信息展示112 【{}】",request);


        String monthValue  =  DateUtils.getStrDate(new Date(), "yyyyMM");

        OrderedShowVo orderedShowVo = new OrderedShowVo();
        Long comId = request.getComId();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("comId", comId);
        jsonObject.put("orderNo", request.getOrderNo());
        jsonObject.put("size", 1);
        jsonObject.put("page", 1);
        jsonObject.put("monthValue", monthValue);

        try {
            Result consumeDetail = xfRecordFeign.getConsumeDetail(jsonObject);
            if (200 != consumeDetail.getCode()) {
                return consumeDetail;
            }
            Map<String, Object> consumeDetailData = JSON.parseObject(JSON.toJSONString(consumeDetail.getData()), HashMap.class);
            List<EntityXfRecord> xfRecordlist = JSON.parseArray(JSON.toJSONString(consumeDetailData.get("list")), EntityXfRecord.class);
            EntityXfRecord entityXfRecord = xfRecordlist.get(0);

            Result mealNameInfo = payConfigClientService.getMealNameInfo(comId, entityXfRecord.getMealNo());
            if (200 != mealNameInfo.getCode()) {
                return mealNameInfo;
            }
            Map<String, Object> mealNameInfoData = JSON.parseObject(JSON.toJSONString(mealNameInfo.getData()), HashMap.class);
            List<EntityXfMealInfo> entityXfMealInfos = JSON.parseArray(JSON.toJSONString(mealNameInfoData.get("list")), EntityXfMealInfo.class);

            OrderedShowRequest orderedShowRequest = new OrderedShowRequest();
            orderedShowRequest.setOrderNo(request.getOrderNo());
            orderedShowRequest.setMonthValue(monthValue);
            orderedShowRequest.setComId(comId);
            Result resultOrderDishesDetail = xfRecordFeign.getOrderDishesDetail(orderedShowRequest);
            if (200 != resultOrderDishesDetail.getCode()) {
                return resultOrderDishesDetail;
            }
            List<OrderedShowDishesListVo> dishesList = JSON.parseArray(JSON.toJSONString(resultOrderDishesDetail.getData()), OrderedShowDishesListVo.class);

            List<Integer> dishesIds = dishesList.stream().map(OrderedShowDishesListVo -> OrderedShowDishesListVo.getDishesId()).collect(Collectors.toList());
            GetDishesInfoDetailListRequest getDishesInfoRequest = new GetDishesInfoDetailListRequest();
            getDishesInfoRequest.setComId(comId);
            getDishesInfoRequest.setDishesIds(dishesIds);
            Result getDishesInfoResult = payConfigClientService.findByComIdAndDishesId(getDishesInfoRequest);
            if (200 != getDishesInfoResult.getCode()) {
                return getDishesInfoResult;
            }
            List<EntityDishesInfo> dishesInfos = JSON.parseArray(JSON.toJSONString(getDishesInfoResult.getData()), EntityDishesInfo.class);
            Map<Integer, EntityDishesInfo> dishesMap = dishesInfos.stream().collect(Collectors.toMap(EntityDishesInfo::getDishesId, EntityDishesInfo -> EntityDishesInfo));
            for (OrderedShowDishesListVo vo : dishesList) {
                vo.setPhotoUrl(dishesMap.get(vo.getDishesId()).getPhotoUrl());
            }
            orderedShowVo.setDishesList(dishesList);

            orderedShowVo.setOrderNo(entityXfRecord.getOrderNo());
            orderedShowVo.setOrderTime(DateUtils.dateToStr(entityXfRecord.getConsTime()));
            orderedShowVo.setMealDate(DateUtils.getStrDate(entityXfRecord.getMealDate(), DateUtils.YYYY_MM_DD));
            orderedShowVo.setMealNo(entityXfRecord.getMealNo());
            if (null != entityXfMealInfos && 0 < entityXfMealInfos.size()) {
                orderedShowVo.setMealName(entityXfMealInfos.get(0).getMealName());
            } else {
                orderedShowVo.setMealName(entityXfRecord.getMealName());
            }
            orderedShowVo.setMerchName(entityXfRecord.getMerchName());
            orderedShowVo.setPointName(entityXfRecord.getPointName());
            orderedShowVo.setDeviceNo(entityXfRecord.getDeviceNo());
            orderedShowVo.setPId(entityXfRecord.getPId().toString());
            orderedShowVo.setPName(entityXfRecord.getPName());
            orderedShowVo.setPCode(entityXfRecord.getPCode());
            orderedShowVo.setReceiptNo(entityXfRecord.getReceiptNo());
            orderedShowVo.setRemark(entityXfRecord.getReserved3());
            orderedShowVo.setReceiptId(entityXfRecord.getReceiptId());
            orderedShowVo.setReceiptName(entityXfRecord.getReceiptName());
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.error(ResultEnum.Err_1001);
        }
        return ResultUtil.success(orderedShowVo);
    }

    /**
     * 6.8就餐时间查询（OrderMealPlan/getMealTime）
     */
    @PostMapping(WxServiceUrl.URL_OrderMealPlanGetMealTime)
    public Result getMealTime(@RequestBody ConsTimeConfigOnShowRequest request) {
        request.setPage(1);
        request.setSize(100);

        Result result = payConfigClientService.GetMealTimeInfo(request);
        if (200 == result.getCode() && null != result.getData()) {
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(result.getData()));
            if (0 == jsonObject.getInteger("total")) {
                request.setPointId(0);
                result = payConfigClientService.GetMealTimeInfo(request);
            }
        }
        return result;
    }


    /**
     * 5.9排餐计划信息（order/mealPlanInfo）
     */
    @PostMapping(WxServiceUrl.URL_mealPlanInfo)
    public Result mealPlanInfo(@RequestBody Map<String, Object> map) {
        MealPlanInfoRequest request = new MealPlanInfoRequest();
        YoCiUser ciUser = SecurityUtils.getYoCiUser();
        request.setComId(ciUser.getComId());
        request.setMealplanId(Integer.valueOf(map.get("mealplanId").toString()));
        return payConfigClientService.mealPlanInfo(request);
    }

}
